# -*- coding: utf-8 -*-
import numpy as np
from datetime import datetime, timedelta
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import platform

class RateCurve:
    def __init__(self, market_quotes):
        """
        初始化利率曲线
        Initialize rate curve
        
        参数/Parameters:
        market_quotes: 市场报价字典，格式为 {期限: 利率}
        market_quotes: Dictionary of market quotes, format {tenor: rate}
        """
        self.market_quotes = market_quotes
        self.tenors = sorted(market_quotes.keys())
        self.rates = [market_quotes[t] for t in self.tenors]
    
    def get_rate(self, target_date):
        """
        计算指定日期的利率
        Calculate rate for specified date
        
        参数/Parameters:
        target_date: 目标日期
        target_date: Target date
        
        返回/Returns:
        float: 目标日期的利率
        float: Rate for target date
        """
        # 将日期转换为年数
        # Convert date to years
        t = self._date_to_years(target_date)
        
        # 找到最近的两个时间点
        # Find nearest two time points
        t1, t2 = self._find_nearest_tenors(t)
        r1 = self.market_quotes[t1]
        r2 = self.market_quotes[t2]
        
        # 线性插值计算利率
        # Calculate rate using linear interpolation
        return r1 + (t - t1) / (t2 - t1) * (r2 - r1)
    
    def _date_to_years(self, date):
        """
        将日期转换为年数
        Convert date to years
        """
        # 假设一年有365天
        # Assume 365 days per year
        return (date - datetime.now()).days / 365.0
    
    def _find_nearest_tenors(self, t):
        """
        找到最近的两个时间点
        Find nearest two time points
        """
        for i in range(len(self.tenors) - 1):
            if self.tenors[i] <= t <= self.tenors[i + 1]:
                return self.tenors[i], self.tenors[i + 1]
        return self.tenors[0], self.tenors[-1]
    
    def get_curve_points(self, end_datetime, num_points=100):
        """
        获取利率曲线上的点
        Get points on the rate curve
        
        参数/Parameters:
        end_datetime: 结束日期
        end_datetime: End date
        num_points: 点的数量
        num_points: Number of points
        
        返回/Returns:
        tuple: (时间点列表, 利率列表)
        tuple: (List of time points, List of rates)
        """
        t_min = min(self.tenors)
        t_max = self._date_to_years(end_datetime)
        t_points = np.linspace(t_min, t_max, num_points)
        r_points = [self.get_rate(datetime.now() + timedelta(days=int(t * 365))) for t in t_points]
        return t_points, r_points
    
    def forward_rate_interval(self, start_date, end_date):
        """
        计算远期利率区间的远期利率
        Calculate forward rate for the interval [start_date, end_date]
        
        参数:
        start_date: 起始日期
        end_date: 结束日期
        
        返回:
        远期利率
        """
        t1 = self._date_to_years(start_date)
        t2 = self._date_to_years(end_date)
        r1 = self.get_rate(start_date)
        r2 = self.get_rate(end_date)
        return (r2 * t2 - r1 * t1) / (t2 - t1)

class RateCurveGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("利率曲线构建工具/Rate Curve Construction Tool")
        
        # 设置字体
        # Set font
        system = platform.system()
        if system == 'Windows':
            default_font = ('Microsoft YaHei', 9)  # Windows 系统使用微软雅黑
        elif system == 'Darwin':
            default_font = ('PingFang SC', 9)  # macOS 系统使用苹方
        else:
            default_font = ('WenQuanYi Micro Hei', 9)  # Linux 系统使用文泉驿微米黑
        
        # 配置 ttk 样式
        # Configure ttk style
        style = ttk.Style()
        style.configure('TLabel', font=default_font)
        style.configure('TButton', font=default_font)
        style.configure('TLabelframe.Label', font=default_font)
        
        # 创建输入框架
        # Create input frame
        input_frame = ttk.LabelFrame(root, text="市场报价/Market Quotes", padding="5")
        input_frame.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
        
        # 创建输入字段
        # Create input fields
        self.rate_vars = {}
        self.create_input_field(input_frame, "1个月/1M", 0, 0.02)
        self.create_input_field(input_frame, "3个月/3M", 1, 0.022)
        self.create_input_field(input_frame, "1年/1Y", 2, 0.025)
        
        # 结束日期输入
        ttk.Label(input_frame, text="结束日期/End Date (YYYY-MM-DD)").grid(row=3, column=0, padx=5, pady=2)
        self.end_date_var = tk.StringVar(value=(datetime.now() + timedelta(days=365)).strftime('%Y-%m-%d'))
        ttk.Entry(input_frame, textvariable=self.end_date_var, width=12).grid(row=3, column=1, padx=5, pady=2)
        
        # 远期利率区间输入
        ttk.Label(input_frame, text="远期利率区间起始日期/Forward Start Date (YYYY-MM-DD)").grid(row=4, column=0, padx=5, pady=2)
        self.forward_start_var = tk.StringVar(value=(datetime.now() + timedelta(days=365)).strftime('%Y-%m-%d'))
        ttk.Entry(input_frame, textvariable=self.forward_start_var, width=12).grid(row=4, column=1, padx=5, pady=2)
        
        ttk.Label(input_frame, text="远期利率区间结束日期/Forward End Date (YYYY-MM-DD)").grid(row=5, column=0, padx=5, pady=2)
        self.forward_end_var = tk.StringVar(value=(datetime.now() + timedelta(days=730)).strftime('%Y-%m-%d'))
        ttk.Entry(input_frame, textvariable=self.forward_end_var, width=12).grid(row=5, column=1, padx=5, pady=2)
        
        # 远期利率显示
        self.forward_rate_label = ttk.Label(input_frame, text="远期利率区间/Forward Rate Interval: ")
        self.forward_rate_label.grid(row=6, column=0, columnspan=2, padx=5, pady=2)
        
        # 创建按钮
        # Create button
        ttk.Button(input_frame, text="更新曲线/Update Curve", 
                  command=self.update_curve).grid(row=7, column=0, columnspan=2, pady=5)
        
        # 创建图形框架
        # Create plot frame
        plot_frame = ttk.LabelFrame(root, text="利率曲线/Rate Curve", padding="5")
        plot_frame.grid(row=0, column=1, padx=5, pady=5, sticky="nsew")
        
        # 创建图形
        # Create plot
        self.fig = Figure(figsize=(6, 4))
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, master=plot_frame)
        self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        
        # 设置matplotlib中文字体
        # Set matplotlib Chinese font
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'Arial Unicode MS']
        plt.rcParams['axes.unicode_minus'] = False
        
        # 初始化曲线
        # Initialize curve
        self.update_curve()
        
        # 配置网格权重
        # Configure grid weights
        root.grid_columnconfigure(1, weight=1)
        root.grid_rowconfigure(0, weight=1)
    
    def create_input_field(self, parent, label, row, default_value):
        """
        创建输入字段
        Create input field
        """
        ttk.Label(parent, text=label).grid(row=row, column=0, padx=5, pady=2)
        var = tk.StringVar(value=str(default_value))
        self.rate_vars[label] = var
        ttk.Entry(parent, textvariable=var, width=10).grid(row=row, column=1, padx=5, pady=2)
    
    def update_curve(self):
        """
        更新利率曲线
        Update rate curve
        """
        # 获取输入值
        # Get input values
        market_quotes = {
            1/12: float(self.rate_vars["1个月/1M"].get()),
            3/12: float(self.rate_vars["3个月/3M"].get()),
            1.0: float(self.rate_vars["1年/1Y"].get())
        }
        
        # 获取结束日期
        # Get end date
        try:
            end_datetime = datetime.strptime(self.end_date_var.get(), '%Y-%m-%d')
        except Exception:
            end_datetime = datetime.now() + timedelta(days=365)
            self.end_date_var.set(end_datetime.strftime('%Y-%m-%d'))
        
        # 创建利率曲线对象
        # Create rate curve object
        curve = RateCurve(market_quotes)
        
        # 获取曲线点
        # Get curve points
        t_points, r_points = curve.get_curve_points(end_datetime)
        
        # 清除旧图
        # Clear old plot
        self.ax.clear()
        
        # 绘制曲线
        # Plot curve
        self.ax.plot(t_points, r_points, 'b-', label='插值曲线/Interpolated Curve')
        self.ax.scatter(curve.tenors, curve.rates, color='red', label='市场报价/Market Quotes')
        
        # 设置标签
        # Set labels
        self.ax.set_xlabel('期限/Tenor (年/Years)')
        self.ax.set_ylabel('利率/Rate')
        self.ax.set_title('利率曲线/Rate Curve')
        self.ax.grid(True)
        self.ax.legend()
        
        # 更新画布
        # Update canvas
        self.canvas.draw()
        
        # 计算远期利率区间
        try:
            forward_start = datetime.strptime(self.forward_start_var.get(), '%Y-%m-%d')
            forward_end = datetime.strptime(self.forward_end_var.get(), '%Y-%m-%d')
            forward_rate = curve.forward_rate_interval(forward_start, forward_end)
            self.forward_rate_label.config(text=f"远期利率区间/Forward Rate Interval: {forward_rate:.4%}")
        except Exception as e:
            self.forward_rate_label.config(text="远期利率区间计算错误/Forward Rate Calculation Error")

def main():
    root = tk.Tk()
    app = RateCurveGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()